package com.sunwayhorizo.health.business.clinic.orders.basedef;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.orders.query.OrdersQueryLocal;
import com.sunwayhorizo.health.business.dto.PageDTO;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.clinic.orders.ObsOrProDTO;
import com.sunwayhorizo.health.business.dto.econ.InvoiceElementDTO;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.datatypes.PQ;
import com.sunwayhorizo.health.hl7.rim.Act;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.ActRelationship;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.InvoiceElement;
import com.sunwayhorizo.health.hl7.rim.Observation;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.rim.SubstanceAdministration;
import com.sunwayhorizo.health.hl7.vocabulary.ActClass;
import com.sunwayhorizo.health.hl7.vocabulary.ActCode;
import com.sunwayhorizo.health.hl7.vocabulary.ActIICode;
import com.sunwayhorizo.health.hl7.vocabulary.ActMood;
import com.sunwayhorizo.health.hl7.vocabulary.ActRelationshipType;
import com.sunwayhorizo.health.hl7.vocabulary.Direction;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleCode;


/**
 * @ClassName ObservationDefManager <br>
 * @PackageName com.sunwayhorizo.health.business.clinic.orders.basedef <br>
 * @Description 诊断观察(检查 检验)定义session bean <br>
 * @Author jinzw <br>
 * @Date 2010-08-23 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate <br>
 * @ModifiedBy <br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */

@Name("ObservationDefManager")
@Stateless
public class ObservationDefManager extends BaseManager implements ObservationDefManagerLocal
{
    private InvoiceElementDefManagerLocal inveElementDefManager = (InvoiceElementDefManagerLocal) Component.getInstance("InvoiceElementDefManager");
    private OrdersQueryLocal ordersQuery = (OrdersQueryLocal) Component.getInstance("OrdersQuery");

    @Override
    public ResultsDTO newObservationDef(ObsOrProDTO obsOrProDTO) throws Hl7Exception
    {
        if(obsOrProDTO == null)
        {
            log.info("检查 检验信息为空，不能添加");
            return this.getResultsDTO("检查 检验信息为空，不能添加", false, null);
        }
        
        //创建检查检验动作
        CE ce = DataTypeUtil.getCE(obsOrProDTO.getCode());
        Observation observation = this.getActFactory().newObservation(ActMood.DEF, ce, null);
        
        //给检查检验动作赋值
        observation = converObsFormObsDto(observation,obsOrProDTO);
        
        //执行科室角色参与到检查检验动作中
        if(StrUtil.isNotEmpty(obsOrProDTO.getExecutDeptRimRoleId()))
        {
            Role exvetuDeptRole = baseQuery.findRoleById(Long.valueOf(obsOrProDTO.getExecutDeptRimRoleId()));
            ActParticipation part = getActFactory().newActParticipation();
            part.setTypeCode(ParticipationType.SBJ);
            addParticipation(exvetuDeptRole, part);
        }
        
        //检查 检验费用信息动作关联到检查 检验定义动作中
        if(ListUtil.isNotEmpty(obsOrProDTO.getInvoiceElementList()))
        {
            for(InvoiceElementDTO invoiceElement : obsOrProDTO.getInvoiceElementList())
            {
                InvoiceElement inve = inveElementDefManager.newInvoiceElementDet(invoiceElement);
                if(inve != null)
                {
                    ActRelationship relation = getActFactory().newActRelationship();
                    relation.setTypeCode(ActRelationshipType.CHRG);
                    addRelationship(inve, relation, Direction.SOURCE);
                }
            }
        }
        
        // 创建ControlAct
        ControlAct control = newControlAct(observation); 
        
        //持久化ControlAct
        save(control);
        log.info("创建检查 检验成功 actid="+observation.getActId());
        return this.getResultsDTO("创建检查 检验信息成功", true, observation.getActId());
    }
  
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public ResultsDTO delObservationDef(List ids) throws Hl7Exception
    {
        if (ListUtil.isEmpty(ids))
        {
            log.info("删除检查 检验信息失败，数据为空");
            return getResultsDTO("删除检查 检验信息失败，数据为空", false, null);
        }
        for(int i=0; i<ids.size(); i++)
        {
            String id = (String)ids.get(i);
            Act act = baseQuery.findActByActId(Long.valueOf(id));
            CS actCode = null;
            if(act.getCode().code().toString().equals(ActCode.EXAM.code().toString()))
            {
                actCode = ActCode.EXAM;
            }
            if(act.getCode().code().toString().equals(ActCode.LAB.code().toString()))
            {
                actCode = ActCode.LAB; 
            }
            List<InvoiceElement> inveList = (List<InvoiceElement>)act.getTargetActListBySourceAct(ActClass.INVE, actCode);
            int j= delete(act,null);
            if(j == 0)
            {
                log.info("检查 检验基本信息删除失败");
            }
            int k = batchDelete(inveList,ParticipationType.IND);
            if(k == 0)
            {
                log.info("检查 检验费用信息删除失败");
            }
        }
        return getResultsDTO("删除检查 检验基本信息成功", true, null);
    }

    @SuppressWarnings({ "unchecked", "null" })
    @Override
    public ResultsDTO updObservationDef(ObsOrProDTO obsOrProDTO) throws Hl7Exception
    {

        if(obsOrProDTO == null && StrUtil.isEmpty(obsOrProDTO.getActId()))
        {
            log.info("检查 检验信息为空,不能进行修改");
            return this.getResultsDTO("检查 检验信息为空，不能修改", false, null);
        }
        
        //得到检查 检验动作
        Observation obs = (Observation)baseQuery.findActByActId(Long.valueOf(obsOrProDTO.getActId()));
        
        //修改检查 检验动作信息
        obs = converObsFormObsDto(obs,obsOrProDTO);
        //修改角色信息
        if(StrUtil.isNotEmpty(obsOrProDTO.getExecutDeptRimRoleId()))
        {
            //修改费用参与角色信息
            ActParticipation part = obs.getParticipations(ParticipationType.SBJ,RoleCode.WORKGROUP);
            if (part != null)
            {
                if (!String.valueOf(part.getRoleParticipation().getRoleId()).equals(obsOrProDTO.getExecutDeptRimRoleId()))
                {
                    Role exvetuDeptRole = baseQuery.findRoleById(Long.valueOf(obsOrProDTO.getExecutDeptRimRoleId()));
                    part.setRoleparticipation(exvetuDeptRole);
                }
            }
            else
            {
                Role exvetuDeptRole = baseQuery.findRoleById(Long.valueOf(obsOrProDTO.getExecutDeptRimRoleId()));
                obs.addPartWithOutEntRole(ParticipationType.SBJ, exvetuDeptRole);
            }
            
        }

       //修改动作信息
        CS actCode = null;
        if (obs.getCode().code().toString().equals(ActCode.EXAM.code().toString()))
        {
            actCode = ActCode.EXAM;
        }
        if (obs.getCode().code().toString().equals(ActCode.LAB.code().toString()))
        {
            actCode = ActCode.LAB;
        }
        List<InvoiceElement> inveList = (List<InvoiceElement>)obs.getTargetActListBySourceAct(ActClass.INVE, actCode);
//        batchDelete(inveList,null);
       
        //治疗费用信息动作关联到治疗定义动作中
//        if(ListUtil.isNotEmpty(obsOrProDTO.getInvoiceElementList()))
//        {
//            for(InvoiceElementDTO invoiceElement : obsOrProDTO.getInvoiceElementList())
//            {
//                InvoiceElement inve = inveElementDefManager.newInvoiceElementDet(invoiceElement);
//                if(inve != null)
//                {
//                    obs.addOBActRelationship(ActRelationshipType.CHRG, inve);
//                }
//            }
//        }         
         List<InvoiceElement> oldInveList = new ArrayList<InvoiceElement>();
        if (ListUtil.isNotEmpty(obsOrProDTO.getInvoiceElementList()))
        {
            for (InvoiceElement inve : inveList)
            {
                boolean flag = true;
                for (int i = 0; i < obsOrProDTO.getInvoiceElementList().size(); i++)
                {
                    InvoiceElementDTO invoiceElement = obsOrProDTO.getInvoiceElementList().get(i);
                    if (String.valueOf(inve.getActId()).equals(invoiceElement.getActId()))
                    {
                        inveElementDefManager.updInvoiceElementDefManager(invoiceElement);
                        obsOrProDTO.getInvoiceElementList().remove(invoiceElement);
                        flag = false;
                        continue;
                    }
                }
                if (flag)
                {
                    oldInveList.add(inve);
                }
            }
            // 新增
            if (ListUtil.isNotEmpty(obsOrProDTO.getInvoiceElementList()))
            {
                for (InvoiceElementDTO invoiceElement : obsOrProDTO.getInvoiceElementList())
                {
                    InvoiceElement inve = inveElementDefManager.newInvoiceElementDet(invoiceElement);
                    if (inve != null)
                    {
                        obs.addOBActRelWhithOutControlAct(ActRelationshipType.CHRG, inve);
                    }
                }
            }
            if (ListUtil.isNotEmpty(oldInveList))
            {
                batchDelete(oldInveList, null);
            }
        }
        else
        {
            batchDelete(inveList, null);
        }
        update(obs);
        log.info("修改检查 检验动作信息成功"+obs.getActId());
  
       return this.getResultsDTO("药品基本信息修改成功", true, obs.getActId().toString());
    }
    

    @SuppressWarnings("unchecked")
    @Override
    public ResultsDTO findObservationDefList(String code,String ywm,PageDTO pageDto) throws Hl7Exception
    {
        if(StrUtil.isEmpty(code) ) return this.getResultsDTO("项目编码为空，不能查询", false, null);
        List<Observation> obsList = (List<Observation>)ordersQuery.findCountObsOrProcByCond(code, ywm, pageDto.getPageNo(), pageDto.getPageSize());
        List<ObsOrProDTO> obsDtoList = new ArrayList<ObsOrProDTO>();
        if(ListUtil.isNotEmpty(obsList))
        {
            for(Observation obs : obsList)
            {
                ObsOrProDTO obsOrProDTO =  converObsDtoFormObs(obs);
                obsDtoList.add(obsOrProDTO);
            }
            pageDto.setTotalRecord((int)ordersQuery.findObsOrProcByCond(code));
        }
        return this.getResultsDTO("查询检查 检验项目成功", true, obsDtoList, pageDto);
    }
    
    private ObsOrProDTO converObsDtoFormObs(Observation obs) throws Hl7Exception
    {
        ObsOrProDTO obsOrProDTO = new ObsOrProDTO();
        obsOrProDTO.setActId(obs.getActId()+"");
        obsOrProDTO.setCode((obs.getCode() != null && obs.getCode().isNull().isFalse() ? obs.getCode().code().toString() : ""));
        II examId = obs.getId(ActIICode.EXAMITEMCODE);
        II labId = obs.getId(ActIICode.LABITEMCODE);
        if(examId != null && examId.isNull().isFalse())
        {
            obsOrProDTO.setId(examId.extension().toString());
        }
        if(labId != null && labId.isNull().isFalse())
        {
            obsOrProDTO.setId(labId.extension().toString());
        }
        obsOrProDTO.setTitle(obs.getTitle().toString());
        obsOrProDTO.setTargetSite(getDictionaryFactory().getDictionaryDTOByCe(obs.getTargetSiteCode()));
        obsOrProDTO.setInterpretation(getDictionaryFactory().getDictionaryDTOByCe(obs.getInterpretationCode()));
        obsOrProDTO.setLabSpecimen(getDictionaryFactory().getDictionaryDTOByCe(obs.getMethodCode()));
        PQ pq = obs.getDurationTIme();
        if(pq != null && pq.isNull().isFalse())
        {
            obsOrProDTO.setDurationTimeValue(pq.value().literal().toString());
            obsOrProDTO.setDurationTimeUnit(pq.unit().literal().toString());
        }
        obsOrProDTO.setInvoiceElementList(converInveElementDTOListFormInves(obs));
        return obsOrProDTO;
    }
    
    private Observation converObsFormObsDto(Observation obs,ObsOrProDTO obsOrProDTO) throws Hl7Exception
    {
        if(obs == null) return null;
        
        //检查 检验项目代码
        if(StrUtil.isNotEmpty(obsOrProDTO.getId()))
        {
            String identifileName = "";
            if(StrUtil.isNotEmpty(obsOrProDTO.getCode()) && obsOrProDTO.getCode().equals(ActCode.EXAM.code().toString()))
            {
                identifileName = ActIICode.EXAMITEMCODE.toString();
            }
            if(StrUtil.isNotEmpty(obsOrProDTO.getCode()) && obsOrProDTO.getCode().equals(ActCode.LAB.code().toString()))
            {
                identifileName = ActIICode.LABITEMCODE.toString(); 
            }
            II id = DataTypeUtil.getII(root, obsOrProDTO.getId(), identifileName);
            obs.setId(id);
        }
        //检查 检验项目名称
        if(StrUtil.isNotEmpty(obsOrProDTO.getTitle()))
        {
            obs.setTitle(DataTypeUtil.getST(obsOrProDTO.getTitle())); 
        }
        //检查部位-临床检验分类
        obs.setTargetSiteCode(getDictionaryFactory().getCeByDictionaryDTO(obsOrProDTO.getTargetSite()));
        //检查方位-检验分类
        obs.setInterpretationCode(getDictionaryFactory().getCeByDictionaryDTO(obsOrProDTO.getInterpretation()));
        //检验标本
        if(obsOrProDTO.getLabSpecimen() != null && StrUtil.isNotEmpty(obsOrProDTO.getLabSpecimen().getConceptCode()))
        {
            obs.setMethodCode(getDictionaryFactory().getCeByDictionaryDTO(obsOrProDTO.getLabSpecimen()));
        }
        //检验报告时间
        obs.setDurationTime(DataTypeUtil.getPQ(obsOrProDTO.getDurationTimeValue(), obsOrProDTO.getDurationTimeUnit()));
        return obs;
    }
    
    //组装药品费用信息dto集合
    @SuppressWarnings({ "unchecked"})
    private List<InvoiceElementDTO> converInveElementDTOListFormInves(Observation obs) throws Hl7Exception
    {
        List<InvoiceElementDTO> inveDtolist = new ArrayList<InvoiceElementDTO>();
        List<InvoiceElement> inves = (List<InvoiceElement>)obs.getTargetActListBySourceAct(ActClass.INVE,obs.getCode());
        if(ListUtil.isNotEmpty(inves))
        {
            for(InvoiceElement inve : inves)
            {
                InvoiceElementDTO inveDto = inveElementDefManager.converInvoiceElementDTOFormInve(inve);
                inveDtolist.add(inveDto);
            }
        }
        return inveDtolist;
    }
}
